
"""
仿真类SUMO，定义仿真过程相关操作
"""

import sys
import time
import traci
import traci.constants as tc
import config
import queuedata
import xml.etree.ElementTree as ET

class SUMO:
    junctions = dict()  # 所有关注路口的Juntion对象
    def __init__(self, sumocfg):
        self.frame = 0
        # 设置sumocfg内容
        self.setSumocfg()

        self.inductionloopid = '##'
        # 更新根据加速倍数更新仿真步长
        traci.start(cmd=['sumo-gui', '--start', '-c', sumocfg, "--num-clients", "1", "--seed", "1"],port=8813)
        self.start = time.perf_counter()
    def subInductionloop(self, inductionloopid, radius):
        """
        订阅感应线圈数据（以检测器inductionloopid为中心，半径radius）
        """
        self.inductionloopid = inductionloopid
        # traci.inductionloop.subscribe(cjunctionid)
        traci.inductionloop.subscribeContext(
            inductionloopid, tc.CMD_GET_INDUCTIONLOOP_VARIABLE, radius, [tc.LAST_STEP_VEHICLE_NUMBER])
                                                                            #  检测器状态，key：16
    def setSumocfg(self):
        sumocfg_tree = ET.parse(config.sumoPath + config.sumoCfg)
        root = sumocfg_tree.getroot()
        for item in root.findall('step-length'):
            item.set('value', '%s' % (config.steplength * config.multiple))
        tree = ET.ElementTree(root)
        tree.write(config.sumoPath + config.sumoCfg)
    def simulation(self):
        """仿真主循环"""
        m = 0
        while True:
            traci.simulationStep()
            self.frame += 1
            m += 1
            if not self.inductionloopid == '##':
                temp = traci.inductionloop.getContextSubscriptionResults(self.inductionloopid)
                queuedata.det_queue.put(temp)
            q_size = queuedata.ryg_queue.qsize()
            while q_size > 0:
                tlsID, newryg = queuedata.ryg_queue.get()
                traci.trafficlight.setRedYellowGreenState(tlsID, newryg)
                traci.trafficlight.setPhaseDuration(tlsID, 999)
                q_size -= 1
            # 帧间休眠
            sleeping = config.steplength*self.frame - (time.perf_counter() - self.start)
            # print(sleeping)
            if sleeping > 0:
                time.sleep(sleeping)
            if m == config.simulationDuration/(config.steplength*config.multiple):
                traci.close()
            sys.stdout.flush()
